/**
 * Pangolin IM Server
 * autor:   yiyefangzhou24
 * email:   yiyefangzhou24@qq.com
 * data:    21/10/1
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "package.h"
#include "receive.h"
#include "function.h"
#include "cJSON.h"
#include "log.h"



/**
 * 登陆响应
 */
void response_login(struct bufferevent *bev,char *buff,size_t len){
    LOG("response_login : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        LOG("response_login : cJSON_Parse error");
        return;
    }

    //校验json数据  消息的json格式，{"username":"user" , "passwd":"pass" , "os":1}
    cJSON * json_uid = cJSON_GetObjectItem(root , "uid");
    cJSON * json_passwd = cJSON_GetObjectItem(root , "passwd");
    cJSON * json_os = cJSON_GetObjectItem(root , "os");
    if(json_uid == NULL || json_passwd == NULL || json_os == NULL){
        cJSON_Delete(root);
        LOG("response_login : cJSON_GetObjectItem error");
        return;
    }
    LOG("response_login : json_uid : %d , json_passwd:%s , json_os:%d" , 
        json_uid->valueint , json_passwd->valuestring , json_os->valueint);

    char key[33] = { 0 };
    int result = RES_OK;
    char msg[256] = { 0 };
    char name[128] = { 0 };
    char headimg[128] = { 0 };
    if(_check_input(IN_UID , &(json_uid->valueint)) &&\
        _check_input(IN_PASSWD , json_passwd->valuestring) &&\
        _check_input(IN_OS , &(json_os->valueint))){
        //密码md5加密
        char passwd_en[40] = { 0 };
        _string_md5encrypt(json_passwd->valuestring , passwd_en);

        //验证用户登陆信息
        if(_check_userlogin(json_uid->valueint , passwd_en)){
            _random_string(key , 32);
            if(_insert_userinfo(json_uid->valueint , key , (int)bufferevent_getfd(bev))){
                //查询用户信息
                if(_response_findfriend(json_uid->valueint , name , headimg)){
                    LOG("response_login : name:%s - headimg:%s" , name , headimg);
                    result = RES_OK;
                }else{
                    result = RES_NOUSER;
                }
            }else{
                result = RES_SYS;
                strcpy(msg , "登陆：创建用户登陆凭证错误");
                LOG("response_login : error : %s" , redis_getlasterror());
            }
        }else{
            result = RES_LOGIN;
            strcpy(msg , "登陆：用户名密码错误");
            LOG("response_login : fail : username or passwd error");
        }
    }else{
        result = RES_FORM;
        strcpy(msg , "登陆：消息格式错误");
        LOG("response_login : fail : data format error");
    }
    

    //构造响应包
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    cJSON_AddItemToObject(re_root, "uid", cJSON_CreateNumber(json_uid->valueint));
    cJSON_AddItemToObject(re_root, "name", cJSON_CreateString(name));
    cJSON_AddItemToObject(re_root, "headimg", cJSON_CreateString(headimg));
    cJSON_AddItemToObject(re_root, "key", cJSON_CreateString(key));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_LOGIN, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);
    cJSON_Delete(re_root);
    cJSON_Delete(root);

}

/**
 * 退出响应
 */
void response_logout(struct bufferevent *bev,char *buff,size_t len){
    LOG("response_logout : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        printf("response_logout : cJSON_Parse error\n");
        return;
    }

    //校验json数据  消息的json格式，{"uid":10000 , "key":"key"}
    cJSON * json_uid = cJSON_GetObjectItem(root , "uid");
    cJSON * json_key = cJSON_GetObjectItem(root , "key");
    if(json_uid == NULL || json_key == NULL){
        cJSON_Delete(root);
        printf("response_logout : cJSON_GetObjectItem error\n");
        return;
    }
    LOG("response_logout : json_uid : %d , json_key:%s" , 
        json_uid->valueint , json_key->valuestring);

    int result = RES_OK;
    char msg[256] = { 0 };
    if(_check_input(IN_UID , &(json_uid->valueint)) &&\
        _check_input(IN_KEY , json_key->valuestring)){
        //验证用户访问令牌
        if(_check_userkey(json_uid->valueint , json_key->valuestring) == false){
            LOG("_check_userkey : check_userkey fail");
            result = RES_KEY;
            strcpy(msg , "注销：访问令牌错误");
        }else{
            if(_response_logout(json_uid->valueint)){
                result = RES_OK;
            }else{
                result = RES_SYS;
                strcpy(msg , "注销：清理访问令牌出错");
                LOG("_response_logout : error");
            }
        }
    }else{
        result = RES_FORM;
        strcpy(msg , "注销：消息格式错误");
        LOG("_check_input : fail : data format error");
    }
    

    //构造响应包
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_LOGOUT, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);
    cJSON_Delete(re_root);
    cJSON_Delete(root);

}

/**
 *  注册响应
 */
void response_register(struct bufferevent *bev,char *buff,size_t len){
    LOG("response_register : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        LOG("response_register : cJSON_Parse error");
        return;
    }

    //校验json数据  消息的json格式，{"username":"user" , "passwd":"pass"}
    cJSON * json_username = cJSON_GetObjectItem(root , "username");
    cJSON * json_passwd = cJSON_GetObjectItem(root , "passwd");
    if(json_username == NULL || json_passwd == NULL){
        cJSON_Delete(root);
        LOG("response_register : cJSON_GetObjectItem error");
        return;
    }
    LOG("response_register : json_username : %s , json_passwd:%s " , 
        json_username->valuestring , json_passwd->valuestring);


    int result = RES_OK;
    int uid = 0;
    char msg[256] = { 0 };
    if(_check_input(IN_USERNAME , json_username->valuestring) && \
        _check_input(IN_PASSWD , json_passwd->valuestring)){
        //密码md5加密
        char passwd_en[40] = { 0 };
        _string_md5encrypt(json_passwd->valuestring , passwd_en);

        //注册用户
        if(_response_register(json_username->valuestring , passwd_en , &uid)){
            result = RES_OK;
        }else{
            result = RES_SYS;
            strcpy(msg , "注册：注册用户失败");
            LOG("_response_register : error");
        }
    }else{
        result = RES_FORM;
        strcpy(msg , "注册：消息格式错误，用户名和密码不能超过64位");
        LOG("_check_input : fail : data format error");
    }
    

    //构造响应包
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    cJSON_AddItemToObject(re_root, "uid", cJSON_CreateNumber(uid));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_REGISTER, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);
    cJSON_Delete(re_root);
    cJSON_Delete(root);

}

/**
 *  修改密码响应
 */
void response_repass(struct bufferevent *bev,char *buff,size_t len){
    LOG("response_repass : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        LOG("response_repass : cJSON_Parse error");
        return;
    }

    //校验json数据  消息的json格式，{"key":"key" , "uid":10000 , "newpasswd":"pass"}
    cJSON * json_key = cJSON_GetObjectItem(root , "key");
    cJSON * json_uid = cJSON_GetObjectItem(root , "uid");
    cJSON * json_newpasswd = cJSON_GetObjectItem(root , "newpasswd");
    if(json_key == NULL || json_uid == NULL || json_newpasswd == NULL){
        cJSON_Delete(root);
        LOG("response_repass : cJSON_GetObjectItem error");
        return;
    }
    LOG("response_register : json_key : %s , json_uid : %d , json_newpasswd:%s " , 
        json_key->valuestring , json_uid->valueint , json_newpasswd->valuestring);


    int result = RES_OK;
    char msg[256] = { 0 };
    if(_check_input(IN_KEY , json_key->valuestring) && \
        _check_input(IN_UID , &(json_uid->valueint)) && \
        _check_input(IN_PASSWD , json_newpasswd->valuestring)){
        //验证用户访问令牌
        if(_check_userkey(json_uid->valueint , json_key->valuestring) == false){
            LOG("_check_userkey : check_userkey fail");
            result = RES_KEY;
            strcpy(msg , "修改密码：访问令牌错误");
        }else{
             //密码md5加密
            char passwd_en[40] = { 0 };
            _string_md5encrypt(json_newpasswd->valuestring , passwd_en);

            //修改密码
            if(_response_repass(json_uid->valueint , passwd_en) > 0){
                result = RES_OK;
            }else{
                result = RES_SYS;
                strcpy(msg , "修改密码：修改密码失败");
                LOG("_response_repass : error");
            }
        }
    }else{
        result = RES_FORM;
        strcpy(msg , "修改密码：消息格式错误，密码不能超过64位");
        LOG("_check_input : fail : data format error");
    }
    

    //构造响应包
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_REPASS, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);
    cJSON_Delete(re_root);
    cJSON_Delete(root);

}

/**
 *  修改用户信息响应
 */
void response_updateuserinfo(struct bufferevent *bev,char *buff,size_t len){
    LOG("response_updateuserinfo : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        LOG("response_updateuserinfo : cJSON_Parse error");
        return;
    }

    //校验json数据  消息的json格式，{"key":"key" , "uid":10000 , "username":"test" , "headimg":"test.jpg"}
    cJSON * json_key = cJSON_GetObjectItem(root , "key");
    cJSON * json_uid = cJSON_GetObjectItem(root , "uid");
    cJSON * json_username = cJSON_GetObjectItem(root , "username");
    cJSON * json_headimg = cJSON_GetObjectItem(root , "headimg");
    if(json_key == NULL || json_uid == NULL || json_username == NULL || json_headimg == NULL){
        cJSON_Delete(root);
        LOG("response_updateuserinfo : cJSON_GetObjectItem error");
        return;
    }
    LOG("response_updateuserinfo : json_key : %s , json_uid : %d , json_username:%s , json_headimg:%s" , 
        json_key->valuestring , json_uid->valueint , json_username->valuestring , json_headimg->valuestring);


    int result = RES_OK;
    char msg[256] = { 0 };
    if(_check_input(IN_KEY , json_key->valuestring) && \
        _check_input(IN_UID , &(json_uid->valueint)) && \
        _check_input(IN_USERNAME , json_username->valuestring) && \
        _check_input(IN_HEADIMG , json_headimg->valuestring)){
        //验证用户访问令牌
        if(_check_userkey(json_uid->valueint , json_key->valuestring) == false){
            LOG("_check_userkey : check_userkey fail");
            result = RES_KEY;
            strcpy(msg , "修改密码：访问令牌错误");
        }else{
            //修改用户信息
            if(_response_updateuserinfo(json_uid->valueint , json_username->valuestring , json_headimg->valuestring) > 0){
                result = RES_OK;
            }else{
                result = RES_SYS;
                strcpy(msg , "修改用户信息：修改用户信息失败");
                LOG("response_updateuserinfo : error");
            }
        }
    }else{
        result = RES_FORM;
        strcpy(msg , "修改用户信息：消息格式错误");
        LOG("response_updateuserinfo :  data format error");
    }
    

    //构造响应包
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_USERINFO, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);
    cJSON_Delete(re_root);
    cJSON_Delete(root);

}

/**
 *  搜索好友响应
 */
void response_findfriend(struct bufferevent *bev,char *buff,size_t len){
    LOG("response_findfriend : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        LOG("response_findfriend : cJSON_Parse error");
        return;
    }

    //校验json数据  消息的json格式，{"key":"md5" , "uid":10000 , "friend_uid":10001}
    cJSON * json_key = cJSON_GetObjectItem(root , "key");
    cJSON * json_uid = cJSON_GetObjectItem(root , "uid");
    cJSON * json_friend_uid = cJSON_GetObjectItem(root , "friend_uid");
    if(json_key == NULL || json_uid == NULL || json_friend_uid == NULL){
        cJSON_Delete(root);
        printf("response_findfriend : cJSON_GetObjectItem error\n");
        return;
    }
    LOG("response_findfriend : json_key : %s , json_uid:%d , json_friend_uid:%d" , 
        json_key->valuestring , json_uid->valueint , json_friend_uid->valueint);


    int result = RES_OK;
    char msg[256] = { 0 };
    int friend_uid = json_friend_uid->valueint;
    char friend_name[128] = { 0 };
    char friend_headimg[128] = { 0 };
    if(_check_input(IN_UID , &(json_friend_uid->valueint)) && \
        _check_input(IN_UID , &(json_uid->valueint)) && \
        _check_input(IN_KEY , json_key->valuestring)){
        //验证用户访问令牌
        if(_check_userkey(json_uid->valueint , json_key->valuestring) == false){
            LOG("_check_userkey : check_userkey fail");
            result = RES_KEY;
            strcpy(msg , "搜索用户：访问令牌错误");
        }else{
            //搜索用户
            _response_findfriend(friend_uid , friend_name , friend_headimg);
            if(strlen(friend_name) > 0){
                result = RES_OK;
            }else{
                result = RES_NOTFRIEND;
                friend_uid = 0;
                strcpy(msg , "搜索用户：用户不存在");
                LOG("_response_findfriend : error");
            }
        }
    }else{
        result = RES_FORM;
        friend_uid = 0;
        strcpy(msg , "搜索用户：消息格式错误");
        LOG("_check_input : fail : data format error");
    }

    //构造响应包
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    cJSON_AddItemToObject(re_root, "friend_uid", cJSON_CreateNumber(friend_uid));
    cJSON_AddItemToObject(re_root, "friend_name", cJSON_CreateString(friend_name));
    cJSON_AddItemToObject(re_root, "friend_headimg", cJSON_CreateString(friend_headimg));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_FINDFRIEND, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);
    cJSON_Delete(re_root);
    cJSON_Delete(root);

}
/**
 * 响应心跳
 */
void response_heartbeat(struct bufferevent *bev, char *buff, size_t len){
    LOG("response_heartbeat : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        LOG("response_heartbeat : cJSON_Parse error");
        return;
    }

    //校验json数据  消息的json格式，{"key":"md5" , "uid":10000}
    cJSON * json_key = cJSON_GetObjectItem(root , "key");
    cJSON * json_uid = cJSON_GetObjectItem(root , "uid");
    if(json_key == NULL || json_uid == NULL){
        cJSON_Delete(root);
        printf("response_heartbeat : cJSON_GetObjectItem error\n");
        return;
    }
    LOG("response_heartbeat : json_key : %s , json_uid:%d" , 
        json_key->valuestring , json_uid->valueint );


    if(_check_input(IN_UID , &(json_uid->valueint)) && \
        _check_input(IN_KEY , json_key->valuestring)){
        //验证用户访问令牌
        if(_check_userkey(json_uid->valueint , json_key->valuestring) == false){
            LOG("response_heartbeat : json_uid : %d : check_userkey fail" , json_uid->valueint);
        }else{
            //跟新用户信息（最后通讯时间）
            if(_update_usertime(json_uid->valueint) == false){
                LOG("response_heartbeat : json_uid : %d : update online time fail" , json_uid->valueint);
            }
        }
    }
    cJSON_Delete(root);
}

/**
 * 响应普通消息（使用消息队列或缓存消息）
 */
void response_message(struct bufferevent *bev, char *buff, size_t len) {
    LOG("response_message : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        printf("response_message : cJSON_Parse error\n");
        return;
    }
     
    //校验json数据  消息的json格式，{"key":"key","mid":"md5","type": 0 , "from":10000 , "to":10001 , "context":"msg","time":}
    cJSON * json_key = cJSON_GetObjectItem(root , "key");
    cJSON * json_mid = cJSON_GetObjectItem(root , "mid");
    cJSON * json_type = cJSON_GetObjectItem(root , "type");
    cJSON * json_fromuid = cJSON_GetObjectItem(root , "from");
    cJSON * json_touid = cJSON_GetObjectItem(root , "to");
    cJSON * json_context = cJSON_GetObjectItem(root , "context");
    cJSON * json_time = cJSON_GetObjectItem(root , "time");
    if(json_mid == NULL || json_type == NULL || json_fromuid == NULL || json_touid == NULL || \
        json_context == NULL || json_key == NULL || json_time == NULL){
        cJSON_Delete(root);
        LOG("response_message : cJSON_GetObjectItem error");
        return;
    }
    LOG("response_message : json_mid : %s , json_type : %d , json_fromuid:%d , json_touid:%d , json_context:%s , json_time:%d" , 
        json_mid->valuestring , json_type->valueint , json_fromuid->valueint , json_touid->valueint , json_context->valuestring , json_time->valueint);

    int result = 1;
    char msg[128] = { 0 };
    if(_check_input(IN_MID , json_mid->valuestring) && \
        _check_input(IN_UID , &(json_fromuid->valueint)) && \
        _check_input(IN_UID , &(json_touid->valueint)) && \
        _check_input(IN_KEY , json_key->valuestring) && \
        _check_input(IN_TYPE , &(json_type->valueint)) && \
        _check_input(IN_CONTEXT , json_context->valuestring)){
        //验证用户访问令牌
        if(_check_userkey(json_fromuid->valueint , json_key->valuestring)){
            //验证好友关系
            if(_check_friend(json_fromuid->valueint , json_touid->valueint) == 1){
                 //重组消息内容
                cJSON * msg_root =  cJSON_CreateObject();
                cJSON_AddItemToObject(msg_root, "type", cJSON_CreateNumber(json_type->valueint));
                cJSON_AddItemToObject(msg_root, "from", cJSON_CreateNumber(json_fromuid->valueint));
                cJSON_AddItemToObject(msg_root, "to", cJSON_CreateNumber(json_touid->valueint));
                cJSON_AddItemToObject(msg_root, "context", cJSON_CreateString(json_context->valuestring));
                cJSON_AddItemToObject(msg_root, "time", cJSON_CreateNumber(json_time->valueint));
                cJSON_AddItemToObject(msg_root, "mid", cJSON_CreateString(json_mid->valuestring));
                char * str_msg = cJSON_PrintUnformatted(msg_root);        
                
                //存入redis或者mysql消息队列
                if(_push_msg_queue(json_fromuid->valueint ,json_touid->valueint , str_msg ,CLI_MESSAGE)){
                    result = RES_OK;
                }else{
                    result = RES_SYS;
                    LOG("response_message : _push_msg_queue error : %s" , str_msg);
                    strcpy(msg , "普通消息：系统错误");
                }
                cJSON_Delete(msg_root);
            }else{
                result = RES_NOTFRIEND;
                strcpy(msg , "普通消息：不是您的好友");
                LOG("response_message : check friend fail");
            }
        }else{
            result = RES_KEY;
            strcpy(msg , "普通消息：访问令牌错误");
            LOG("_check_userkey : check_userkey fail");
        }
    }else{
        result = RES_FORM;
        strcpy(msg , "普通消息：消息格式错误");
        LOG("_check_input : fail : data format error");
    }
    

    //返回结果
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "mid", cJSON_CreateString(json_mid->valuestring));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_MESSAGE, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);

    cJSON_Delete(re_root);
    cJSON_Delete(root);
}

/**
 * 响应拉取离线消息
 */
void response_off_message(struct bufferevent *bev, char *buff, size_t len) {
    LOG("response_off_message : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        printf("response_off_message : cJSON_Parse error\n");
        return;
    }
     
    //校验json数据  消息的json格式，{"key":"key", "uid":10000}
    cJSON * json_key = cJSON_GetObjectItem(root , "key");
    cJSON * json_uid = cJSON_GetObjectItem(root , "uid");
    if(json_uid == NULL || json_key == NULL ){
        cJSON_Delete(root);
        LOG("response_off_message : cJSON_GetObjectItem error");
        return;
    }
    LOG("response_off_message : json_key : %s , json_uid:%d " , 
        json_key->valuestring , json_uid->valueint);

    int result = RES_OK;
    char msg[256] = { 0 };
    if(_check_input(IN_UID , &(json_uid->valueint)) && \
        _check_input(IN_KEY , json_key->valuestring)){
        //验证用户访问令牌
        if(_check_userkey(json_uid->valueint , json_key->valuestring)){
            //拉取离线消息队列消息，为避免消息过多一次查询数据库申请内存出错，改为多次查询
            int num = 0;
            struct evbuffer *out_msg = bufferevent_get_output(bev);
            do{
                char msg_arr[20][PACKAGE_BUFF_MAX_LEN] = { { 0 } };
                num = _pull_msg_queue(json_uid->valueint , msg_arr);
                LOG("response_off_message : msg_num : %d" , num);
                
                for (int i = 0 ; i < num ; i ++){
                    //分离操作码和json数据
                    char str_cmd[10] = { 0 };
                    char str_data[PACKAGE_BUFF_MAX_LEN] = { 0 };
                    int cur = (int )(strchr(msg_arr[i] , ':') - msg_arr[i]);
                    if(cur <= 0) {
                        LOG( "offline msg format error : %s", msg_arr[i]);
                        continue;
                    }
                    strncpy(str_cmd , msg_arr[i] , cur);
                    int cmd = atoi(str_cmd);
                    strcpy(str_data , msg_arr[i] + cur + 1);

                    LOG("_offline_msg : %d , %s" , i , str_data);

                    char * str_msg_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_data) + 1);
                    memset(str_msg_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_data) + 1);
                    package_new( str_data,strlen( str_data),1,cmd, str_msg_package);

                    evbuffer_add(out_msg,str_msg_package,sizeof(PACKAGE_HEAD) + strlen( str_data));
                    free(str_msg_package);
                }
            }while(num > 0);
            cJSON_Delete(root);
            return;
        }else{
            result = RES_KEY;
            LOG("response_off_message : check_userkey fail");
            strcpy(msg , "离线消息：访问令牌错误");
        }
    }else{
        result = RES_FORM;
        strcpy(msg , "离线消息：消息格式错误");
        LOG("_check_input : fail : data format error");
    }

    //返回结果
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_OFF_MESSAGE, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);

    cJSON_Delete(re_root);
    cJSON_Delete(root);
}

/**
 * 发起添加好友消息（使用消息队列或缓存消息）
 */
void response_operatefriend(struct bufferevent *bev, char *buff, size_t len){
    LOG("response_operatefriend : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        printf("response_operatefriend : cJSON_Parse error\n");
        return;
    }
     
    //校验json数据  消息的json格式，{"key":"key", "from":10000,"to":10001 , "context":"","pubkey":""}
    cJSON * json_key = cJSON_GetObjectItem(root , "key");
    cJSON * json_from = cJSON_GetObjectItem(root , "from");
    cJSON * json_to = cJSON_GetObjectItem(root , "to");
    cJSON * json_context = cJSON_GetObjectItem(root , "context");
    cJSON * json_pubkey = cJSON_GetObjectItem(root , "pubkey");
    if(json_key == NULL || json_from == NULL || json_to == NULL || json_context == NULL ||json_pubkey == NULL){
        cJSON_Delete(root);
        LOG("response_operatefriend : cJSON_GetObjectItem error");
        return;
    }
    LOG("response_operatefriend : json_key : %s , json_from:%d , json_to:%d , json_context:%s , json_pubkey:%s" , 
        json_key->valuestring , json_from->valueint , json_to->valueint , \
        json_context->valuestring , json_pubkey->valuestring);

    int result = RES_OK;
    char msg[256] = { 0 };
    if(_check_input(IN_UID , &(json_from->valueint)) && \
        _check_input(IN_UID , &(json_to->valueint)) && \
        _check_input(IN_KEY , json_key->valuestring) && \
        _check_input(IN_CONTEXT , json_context->valuestring) && \
        _check_input(IN_PUBKEY , json_pubkey->valuestring)){
        //验证用户访问令牌
        if(_check_userkey(json_from->valueint , json_key->valuestring)){
            //验证不能是自己加自己
            if(json_from->valueint != json_to->valueint){
                //验证好友是否存在
                char username_to[128] = { 0 };
                char username_from[128] = { 0 };
                char headimg_to[128] = { 0 };
                char headimg_from[128] = { 0 };
                if(_response_findfriend(json_to->valueint , username_to , headimg_to)   \
                    && _response_findfriend(json_from->valueint , username_from , headimg_from)){
                    //验证好友关系
                    int ret = _check_friend(json_from->valueint , json_to->valueint);
                    if(ret == -1){   //没有任何联系，这时候需要写入mysql好友关系表，remark设置为0（表示尚未确认），并发消息通知对方
                        if(_add_friendlist(json_from->valueint , json_to->valueint , 0)){
                            //重组消息内容
                            cJSON * msg_root =  cJSON_CreateObject();
                            cJSON_AddItemToObject(msg_root, "from", cJSON_CreateNumber(json_from->valueint));
                            cJSON_AddItemToObject(msg_root, "to", cJSON_CreateNumber(json_to->valueint));
                            cJSON_AddItemToObject(msg_root, "context", cJSON_CreateString(json_context->valuestring));
                            cJSON_AddItemToObject(msg_root, "name", cJSON_CreateString(username_from));
                            cJSON_AddItemToObject(msg_root, "headimg", cJSON_CreateString(headimg_from));
                            cJSON_AddItemToObject(msg_root, "pubkey", cJSON_CreateString(json_pubkey->valuestring));
                            char * str_msg = cJSON_PrintUnformatted(msg_root);        
                            
                            //存入redis或者mysql消息队列
                            if(_push_msg_queue(json_from->valueint ,json_to->valueint , str_msg , CLI_OPERATEFRIEND)){
                                result = RES_OK;
                            }else{
                                result = RES_SYS;
                                LOG("response_operatefriend : _push_msg_queue error : %s" , str_msg);
                                strcpy(msg , "添加好友：写入消息队列错误");
                            }
                            cJSON_Delete(msg_root);
                        }else{
                            result = RES_SYS;
                            LOG("response_operatefriend : _add_friendlist error : from: %d , to:%d" , json_from->valueint,json_to->valueint);
                            strcpy(msg , "添加好友：写入数据库错误");
                        }
                    }else if(ret == 0){     //已经发起过申请，但对方还未通过，这时候只需要重新发送消息通知对方即可
                        //重组消息内容
                        cJSON * msg_root =  cJSON_CreateObject();
                        cJSON_AddItemToObject(msg_root, "from", cJSON_CreateNumber(json_from->valueint));
                        cJSON_AddItemToObject(msg_root, "to", cJSON_CreateNumber(json_to->valueint));
                        cJSON_AddItemToObject(msg_root, "context", cJSON_CreateString(json_context->valuestring));
                        cJSON_AddItemToObject(msg_root, "name", cJSON_CreateString(username_from));
                        cJSON_AddItemToObject(msg_root, "headimg", cJSON_CreateString(headimg_from));
                        cJSON_AddItemToObject(msg_root, "pubkey", cJSON_CreateString(json_pubkey->valuestring));
                        char * str_msg = cJSON_PrintUnformatted(msg_root);        
                        
                        //存入redis或者mysql消息队列
                        if(_push_msg_queue(json_from->valueint ,json_to->valueint , str_msg , CLI_OPERATEFRIEND)){
                            result = RES_OK;
                        }else{
                            result = RES_SYS;
                            LOG("response_operatefriend : _push_msg_queue error : %s" , str_msg);
                            strcpy(msg , "添加好友：写入消息队列错误");
                        }
                        cJSON_Delete(msg_root);
                    }else{              //已经是好友，则返回错误
                        result = RES_FRIENDED;
                        LOG("response_operatefriend : already friend");
                        strcpy(msg , "添加好友：已经互为好友，无需再添加");
                    }
                }else{
                    result = RES_NOTFRIEND;
                    LOG("response_operatefriend : check_userkey fail");
                    strcpy(msg , "添加好友：好友不存在");
                }
            }else{
                result = RES_SAMEID;
                LOG("response_operatefriend : cannot add youself");
                strcpy(msg , "添加好友：不能添加自己");
            }
        }else{
            result = RES_KEY;
            LOG("response_operatefriend : check_userkey fail");
            strcpy(msg , "添加好友：访问令牌错误");
        }
    }else{
        result = RES_FORM;
        strcpy(msg , "添加好友：消息格式错误");
        LOG("response_operatefriend : fail : data format error");
    }

    //返回结果
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_OPERATEFRIEND, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);

    cJSON_Delete(re_root);
    cJSON_Delete(root);

}

/**
 * 确认添加好友消息（使用消息队列或缓存消息）
 */
void response_confirmfriend(struct bufferevent *bev, char *buff, size_t len){
    LOG("response_confirmfriend : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        printf("response_confirmfriend : cJSON_Parse error\n");
        return;
    }
     
    //校验json数据  消息的json格式，{"key":"key", "result":1 , from":10001,"to":10000 , "pubkey":""}
    cJSON * json_key = cJSON_GetObjectItem(root , "key");
    cJSON * json_from = cJSON_GetObjectItem(root , "from");
    cJSON * json_to = cJSON_GetObjectItem(root , "to");
    cJSON * json_result = cJSON_GetObjectItem(root , "result");
    cJSON * json_pubkey = cJSON_GetObjectItem(root , "pubkey");
    if(json_key == NULL || json_from == NULL || json_to == NULL || json_result == NULL ||json_pubkey == NULL){
        cJSON_Delete(root);
        LOG("response_confirmfriend : cJSON_GetObjectItem error");
        return;
    }
    LOG("response_confirmfriend : json_key : %s , json_from:%d , json_to:%d , json_result:%d , json_pubkey:%s" , 
        json_key->valuestring , json_from->valueint , json_to->valueint, \
        json_result->valueint , json_pubkey->valuestring);

    int result = RES_OK;
    char msg[256] = { 0 };
    if(_check_input(IN_UID , &(json_from->valueint)) && \
        _check_input(IN_UID , &(json_to->valueint)) && \
        _check_input(IN_KEY , json_key->valuestring) && \
        _check_input(IN_RESULT , &(json_result->valueint)) && \
        _check_input(IN_PUBKEY , json_pubkey->valuestring)){
        //验证用户访问令牌
        if(_check_userkey(json_from->valueint , json_key->valuestring)){
            if(json_result->valueint == 1){  //接受好友申请
                //更新mysql好友关系表，remark设置为1（表示尚已确认）
                if(_update_friendlist(json_from->valueint , json_to->valueint , 1)){
                    //重组消息内容
                    cJSON * msg_root =  cJSON_CreateObject();
                    cJSON_AddItemToObject(msg_root, "from", cJSON_CreateNumber(json_from->valueint));
                    cJSON_AddItemToObject(msg_root, "to", cJSON_CreateNumber(json_to->valueint));
                    cJSON_AddItemToObject(msg_root, "pubkey", cJSON_CreateString(json_pubkey->valuestring));
                    char * str_msg = cJSON_PrintUnformatted(msg_root);        
                    
                    //存入redis或者mysql消息队列
                    if(_push_msg_queue(json_from->valueint ,json_to->valueint , str_msg , CLI_CONFIRMFRIEND)){
                        result = RES_OK;
                    }else{
                        result = RES_SYS;
                        LOG("response_confirmfriend : _push_msg_queue error : %s" , str_msg);
                        strcpy(msg , "确认添加好友：写入消息队列错误");
                    }
                    cJSON_Delete(msg_root);
                }else{
                    result = RES_SYS;
                    LOG("response_confirmfriend : _update_friendlist error : from: %d , to:%d" , json_from->valueint,json_to->valueint);
                    strcpy(msg , "确认添加好友：更新好友关系数据库错误");
                }
            }else{          //拒绝好友申请则什么都不做，直接返回
                result = RES_OK;
            }
        }else{
            result = RES_KEY;
            LOG("response_confirmfriend : check_userkey fail");
            strcpy(msg , "确认添加好友：访问令牌错误");
        }
    }else{
        result = RES_FORM;
        strcpy(msg , "确认添加好友：消息格式错误");
        LOG("response_confirmfriend : fail : data format error");
    }

    //返回结果
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_CONFIRMFRIEND, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);

    cJSON_Delete(re_root);
    cJSON_Delete(root);

}

/**
 * 删除好友消息（使用消息队列或缓存消息）
 */
void response_delfriend(struct bufferevent *bev, char *buff, size_t len){
    LOG("response_delfriend : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        printf("response_delfriend : cJSON_Parse error\n");
        return;
    }
     
    //校验json数据  消息的json格式，{"key":"key", from":10001,"to":10000 }
    cJSON * json_key = cJSON_GetObjectItem(root , "key");
    cJSON * json_from = cJSON_GetObjectItem(root , "from");
    cJSON * json_to = cJSON_GetObjectItem(root , "to");
    if(json_key == NULL || json_from == NULL || json_to == NULL){
        cJSON_Delete(root);
        LOG("response_delfriend : cJSON_GetObjectItem error");
        return;
    }
    LOG("response_delfriend : json_key : %s , json_from:%d , json_to:%d" , 
        json_key->valuestring , json_from->valueint , json_to->valueint);

    int result = RES_OK;
    char msg[256] = { 0 };
    if(_check_input(IN_UID , &(json_from->valueint)) && \
        _check_input(IN_UID , &(json_to->valueint)) && \
        _check_input(IN_KEY , json_key->valuestring)){
        //验证用户访问令牌
        if(_check_userkey(json_from->valueint , json_key->valuestring)){
            //验证是否是好友关系
            if(_check_friend(json_from->valueint , json_to->valueint) == 1){
                if(_del_friendlist(json_from->valueint , json_to->valueint)){
                    //重组消息内容
                    cJSON * msg_root =  cJSON_CreateObject();
                    cJSON_AddItemToObject(msg_root, "from", cJSON_CreateNumber(json_from->valueint));
                    cJSON_AddItemToObject(msg_root, "to", cJSON_CreateNumber(json_to->valueint));
                    char * str_msg = cJSON_PrintUnformatted(msg_root);        
                    
                    //存入redis或者mysql消息队列
                    if(_push_msg_queue(json_from->valueint ,json_to->valueint , str_msg , CLI_DELFRIEND)){
                        result = RES_OK;
                    }else{
                        result = RES_SYS;
                        LOG("response_delfriend : _push_msg_queue error : %s" , str_msg);
                        strcpy(msg , "删除好友：写入消息队列错误");
                    }
                    cJSON_Delete(msg_root);
                }else{
                    result = RES_SYS;
                    LOG("response_delfriend : _del_friendlist : error");
                    strcpy(msg , "删除好友：系统错误");
                }
            }else{
                result = RES_NOTFRIEND;
                LOG("response_delfriend : _check_friend : not friend");
                strcpy(msg , "删除好友：不是好友关系");
            }
        }else{
            result = RES_KEY;
            LOG("response_delfriend : check_userkey fail");
            strcpy(msg , "删除好友：访问令牌错误");
        }
    }else{
        result = RES_FORM;
        strcpy(msg , "删除好友：消息格式错误");
        LOG("response_delfriend : fail : data format error");
    }

    //返回结果
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_DELFRIEND, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);

    cJSON_Delete(re_root);
    cJSON_Delete(root);

}

/**
 * 获取联系人列表消息
 */
void response_friendlist(struct bufferevent *bev, char *buff, size_t len) {
    LOG("response_friendlist : body_buff:%s" , buff);

    //解析json格式数据
    cJSON * root = cJSON_Parse(buff);
    if(root == NULL){
        cJSON_Delete(root);
        printf("response_friendlist : cJSON_Parse error\n");
        return;
    }
     
    //校验json数据  消息的json格式，{"key":"key", "uid":10000}
    cJSON * json_key = cJSON_GetObjectItem(root , "key");
    cJSON * json_uid = cJSON_GetObjectItem(root , "uid");
    if(json_uid == NULL || json_key == NULL ){
        cJSON_Delete(root);
        LOG("response_friendlist : cJSON_GetObjectItem error");
        return;
    }
    LOG("response_friendlist : json_key : %s , json_uid:%d " , 
        json_key->valuestring , json_uid->valueint);

    int result = RES_OK;
    char msg[256] = { 0 };
    if(_check_input(IN_UID , &(json_uid->valueint)) && \
        _check_input(IN_KEY , json_key->valuestring)){
        //验证用户访问令牌
        if(_check_userkey(json_uid->valueint , json_key->valuestring)){
            //获取好友个数
            int num = _count_friendlistbyuid(json_uid->valueint);
            
            if(num > 0){
                //初始化int数组存放好友uid表
                int *uid_list = (int *)malloc(sizeof(int) * num);

                //初始化二维字符串数组存放好友用户名表
                char **name_list = (char**)malloc(sizeof(char *) * num);
                for (int i = 0; i < num; i++)
                {
                    name_list[i] = (char *)malloc(sizeof(char) * 128);
                }

                //初始化二维字符串数组存放好友头像表
                char **headimg_list = (char**)malloc(sizeof(char *) * num);
                for (int i = 0; i < num; i++)
                {
                    headimg_list[i] = (char *)malloc(sizeof(char) * 128);
                }

                num = _get_friendlist(json_uid->valueint , uid_list , name_list , headimg_list);

                //返回联系人列表
                int num_once = 1;       //一个包最多存放10个联系人
                int round = num % num_once == 0 ? num / num_once : (num / num_once) + 1; //计算需要发送的次数
                for(int i = 0 ; i < round ; i ++){
                    //返回结果
                    cJSON * contacts_root =  cJSON_CreateObject();
                    cJSON_AddItemToObject(contacts_root, "result", cJSON_CreateNumber(result));
                    cJSON_AddItemToObject(contacts_root, "msg", cJSON_CreateString(msg));
                    cJSON_AddItemToObject(contacts_root, "num", cJSON_CreateNumber(num));
                    cJSON * contacts_array = cJSON_CreateArray();
                    int cur = i * num_once;     //计算当前联系人游标位置
                    for(int j = cur ; (j < cur + num_once ) && (j < num) ; j ++){
                        cJSON * contacts_item = cJSON_CreateObject();
                        cJSON_AddItemToObject(contacts_item, "uid", cJSON_CreateNumber(uid_list[j]));
                        cJSON_AddItemToObject(contacts_item, "name", cJSON_CreateString(name_list[j]));
                        cJSON_AddItemToObject(contacts_item, "headimg", cJSON_CreateString(headimg_list[j]));
                        cJSON_AddItemToArray(contacts_array, contacts_item);
                    }
                    cJSON_AddItemToObject(contacts_root, "contacts", contacts_array);
                    char * str_contacts = cJSON_PrintUnformatted(contacts_root);
                    char * str_contacts_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_contacts) + 1);
                    memset(str_contacts_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_contacts) + 1);
                    package_new(str_contacts,strlen(str_contacts),1,COM_RE_FRIENDLIST, str_contacts_package);

                    //发送数据
                    struct evbuffer *out;
                    out = bufferevent_get_output(bev);
                    evbuffer_add(out,str_contacts_package,sizeof(PACKAGE_HEAD) + strlen(str_contacts));

                    free(str_contacts_package);

                    cJSON_Delete(contacts_root);
                }

                //清理环境
                for (int i = 0; i < num; i++){
                    free(name_list[i]);
                }
                for (int i = 0; i < num; i++){
                    free(headimg_list[i]);
                }
                free(uid_list);
                free(name_list);
                free(headimg_list);
            }else{
                //返回结果
                cJSON * contacts_root =  cJSON_CreateObject();
                cJSON_AddItemToObject(contacts_root, "result", cJSON_CreateNumber(result));
                cJSON_AddItemToObject(contacts_root, "msg", cJSON_CreateString(msg));
                cJSON_AddItemToObject(contacts_root, "num", cJSON_CreateNumber(0));
                char * str_contacts = cJSON_PrintUnformatted(contacts_root);
                char * str_contacts_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_contacts) + 1);
                memset(str_contacts_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_contacts) + 1);
                package_new(str_contacts,strlen(str_contacts),1,COM_RE_FRIENDLIST, str_contacts_package);

                //发送数据
                struct evbuffer *out;
                out = bufferevent_get_output(bev);
                evbuffer_add(out,str_contacts_package,sizeof(PACKAGE_HEAD) + strlen(str_contacts));

                free(str_contacts_package);

                cJSON_Delete(contacts_root);
            }
            cJSON_Delete(root);
            return;         //直接返回
        }else{
            result = RES_KEY;
            LOG("response_friendlist : check_userkey fail");
            strcpy(msg , "获取联系人列表：访问令牌错误");
        }
    }else{
        result = RES_FORM;
        strcpy(msg , "获取联系人列表：消息格式错误");
        LOG("response_friendlist : fail : data format error");
    }

    //返回结果
    cJSON * re_root =  cJSON_CreateObject();
    cJSON_AddItemToObject(re_root, "result", cJSON_CreateNumber(result));
    cJSON_AddItemToObject(re_root, "msg", cJSON_CreateString(msg));
    char * str_ret = cJSON_PrintUnformatted(re_root);
    char * str_package = malloc(sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    memset(str_package , 0 , sizeof(PACKAGE_HEAD) + strlen(str_ret) + 1);
    package_new(str_ret,strlen(str_ret),1,COM_RE_OFF_MESSAGE, str_package);

    //发送数据
    struct evbuffer *out;
    out = bufferevent_get_output(bev);
    evbuffer_add(out,str_package,sizeof(PACKAGE_HEAD) + strlen(str_ret));

    free(str_package);

    cJSON_Delete(re_root);
    cJSON_Delete(root);
}

void receive_buff(struct bufferevent *bev,char *buff){
    PACKAGE_HEAD head;
    get_package_head(&head , buff);

    LOG("package_head : %d " , head.package_len);
    LOG("head_len : %hd " , head.head_len);
    LOG("version : %hd " , head.version);
    LOG("command : %d " , head.command);
    LOG("idx : %d " , head.idx);

    size_t len = head.package_len - head.head_len;
    char *body_buff = buff + head.head_len;
    switch (head.command){
        case COM_MESSAGE:
            response_message(bev,body_buff,len);
            break;
        case COM_OFF_MESSAGE:
            response_off_message(bev,body_buff,len);
            break;
        case COM_HEARTBEAT:
            response_heartbeat(bev, body_buff, len);
            break;
        case COM_REGISTER:
            response_register(bev , body_buff , len);
            break;
        case COM_LOGIN:
            response_login(bev , body_buff , len);
            break;
        case COM_FINDFRIEND:
            response_findfriend(bev , body_buff , len);
            break;
        case COM_LOGOUT:
            response_logout(bev , body_buff , len);
            break;
        case COM_REPASS:
            response_repass(bev , body_buff , len);
            break;
        case COM_USERINFO:
            response_updateuserinfo(bev , body_buff , len);
            break;
        case COM_OPERATEFRIEND:
            response_operatefriend(bev , body_buff , len);
            break;
        case COM_CONFIRMFRIEND:
            response_confirmfriend(bev , body_buff , len);
            break;
        case COM_DELFRIEND:
            response_delfriend(bev , body_buff , len);
            break;
        case COM_FRIENDLIST:
            response_friendlist(bev , body_buff , len);
            break;
    }
    // free(package_head);
}